package com.example.demo.config;

import com.alibaba.fastjson.JSON;
import com.example.demo.common.BaseResult;
import com.example.demo.constant.DataBaseConstants;
import com.example.demo.constant.DataBaseType;
import net.hasor.core.ApiBinder;
import net.hasor.core.DimModule;
import net.hasor.dataql.DataQL;
import net.hasor.dataql.compiler.qil.QIL;
import net.hasor.dataql.fx.db.FxSqlCheckChainSpi;
import net.hasor.dataway.spi.*;
import net.hasor.db.JdbcModule;
import net.hasor.db.Level;
import net.hasor.spring.SpringModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 模型配置
 *
 * @author Administrator
 */
@DimModule
@Component
public class ConfigModule implements SpringModule {

    @Autowired
    @Qualifier("greenplum")
    private DataSource greenplumDataSource = null;

    @Autowired
    @Qualifier("mysql")
    private DataSource mysqlDataSource = null;

    @Override
    public void loadModule(ApiBinder apiBinder) throws Throwable {

        Map<String, DataSource> dataSourcePool = new HashMap<>(2);
        dataSourcePool.put("Greenplum", greenplumDataSource);
        dataSourcePool.put("MySQL", mysqlDataSource);

        // 数据源配置（服务配置库）
        apiBinder.installModule(new JdbcModule(Level.Full, dataSourcePool.get(DataBaseConstants.USE_TYPE)));


        // 如果存在后续 那么继续执行检查，否则使用 EXIT 常量控制退出后续的检查。
        apiBinder.bindSpiListener(FxSqlCheckChainSpi.class, infoObject -> {
            System.out.println(String.format("[%s] %s", infoObject.getSourceName(), infoObject.getQueryString().trim()));
            // 可以用来查看执行的 SQL 或统一修改某些规则。
            return FxSqlCheckChainSpi.NEXT;
        });

        apiBinder.bindSpiListener(PreExecuteChainSpi.class, (apiInfo, future) -> {
            apiInfo.getParameterMap().put("self", "me");
        });

        // 编译拦截器（统一处理SQL方言）
        apiBinder.bindSpiListener(CompilerSpiListener.class, new CompilerSpiListener() {
            @Override
            public QIL compiler(ApiInfo apiInfo, String query, DataQL dataQl) throws IOException {
                if (query.contains(DataBaseType.MySQL.value)) {
                    query = "hint FRAGMENT_SQL_PAGE_DIALECT = \"mysql\" ;" + query;
                } else {
                    query = "hint FRAGMENT_SQL_PAGE_DIALECT = \"postgresql\" ;" + query;
                }
                return dataQl.compilerQuery(query);
            }
        });

        // 二进制序列化
//        apiBinder.bindSpiListener(SerializationChainSpi.class, (apiInfo, mimeType, result) -> {
//            BufferedImage bi = new BufferedImage(150, 70, BufferedImage.TYPE_INT_RGB); //高度70,宽度150
//            Graphics2D g2 = (Graphics2D) bi.getGraphics();
//            // background color
//            g2.fillRect(0, 0, 150, 70);
//            g2.setColor(Color.WHITE);
//            // text
//            g2.setFont(new Font("宋体", Font.BOLD, 18));
//            g2.setColor(Color.BLACK);
//            g2.drawString(String.valueOf(result), 3, 50);
//            // save to bytes
//            ByteArrayOutputStream oat = new ByteArrayOutputStream();
//            try {
//                ImageIO.write(bi, "JPEG", oat);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            // response
//            return SerializationChainSpi.SerializationInfo.ofBytes(//
//                    mimeType.getMimeType("jpeg"),   // response context-type
//                    oat.toByteArray()               // response body
//            );
//        });

        // 不输出为空数据
        apiBinder.bindSpiListener(SerializationChainSpi.class, (apiInfo, mimeType, result) -> JSON.toJSONString(result));

        // 返回结果封装
        apiBinder.bindSpiListener(ResultProcessChainSpi.class, new ResultProcessChainSpi() {
            @Override
            public Object callAfter(boolean formPre, ApiInfo apiInfo, Object result) {
                return BaseResult.getInstance(result);
            }
        });

    }
}
